package com.group.controller;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.base.view.ListResult;
import com.group.dao.InviteRebateDao;
import com.group.model.*;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Controller;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSONObject;
import com.base.view.GeneralResult;
import com.google.gson.JsonObject;
import com.group.util.NoteException;
import com.group.util.WeiXinConf;
import com.group.util.WeiXinUtils;

/**
 * 交易所购买接口
 * 
 * @author zhaolei
 *
 */
@Controller
public class ExchangeBuyController extends BaseController {
	private static final Logger logger = LoggerFactory.getLogger(ExchangeBuyController.class);

	@Autowired
	InviteRebateDao inviteRebateDao;

	/**
	 * 预支付接口
	 * 
	 * @param openid
	 *            wecc的openid
	 * @param userId
	 * @param amount
	 *            充值金额,分
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "/exchange/pay/prepay", method = RequestMethod.GET)
	@ResponseBody
	public GeneralResult<JSAPI> prepay(String openid, Long userId, Integer amount) throws Exception {
		if (StringUtils.isEmpty(openid) || userId == null || amount == null) {
			throw new NoteException("openid ,userId , amount 不能为空");
		}

		// fee = "0.01";
		if (amount < 100)
			throw new NoteException("充值今天不能小于1块");

		File file = new ClassPathResource("/prepay.txt").getFile();

		String xml = FileUtils.readFileToString(file);

		String body = getSystemParaValue("wxpayMsg");
		String noncestr = "feifan250";
		String notifyUrl = getSystemParaValue("baseUrl") + "/v1/exchange/pay/notify";
		// String openid = "ofLmEwbf21cDMNSxWThSrc-VpVyg";
		String outTradeNo = getBillNum();

		OutTradeNoLog log = new OutTradeNoLog();
		log.setState(0);
		log.setOutTradeNo(outTradeNo);
		log.setUserId(userId);
		log.setFee(amount);
		beanDao.save(log);

		// 额外信息
		String attach = userId.toString() + "-" + outTradeNo + "-" + amount;
		String ip = "127.0.0.1";

		// String fee = getSystemParaValue("registFee");
		String totalFee = amount + "";

		xml = xml.replace("$appid", WeiXinConf.WECCAPPID);
		xml = xml.replace("$attach", attach);
		xml = xml.replace("$body", body);
		xml = xml.replace("$mchid", WeiXinConf.WECC_SHOP_ID);
		xml = xml.replace("$noncestr", noncestr);
		xml = xml.replace("$notifyUrl", notifyUrl);
		xml = xml.replace("$openid", openid);
		xml = xml.replace("$outTradeNo", outTradeNo);
		xml = xml.replace("$ip", ip);
		xml = xml.replace("$totalFee", totalFee);

		String signStr = "appid=" + WeiXinConf.WECCAPPID + "&attach=" + attach + "&body=" + body + "&mch_id=" + WeiXinConf.WECC_SHOP_ID + "&nonce_str=" + noncestr + "&notify_url=" + notifyUrl + "&openid="
				+ openid + "&out_trade_no=" + outTradeNo + "&spbill_create_ip=" + ip + "&total_fee=" + totalFee + "&trade_type=JSAPI&key=" + WeiXinConf.WECC_SHOP_SECRET;

		String sign = WeiXinUtils.getMD5Code(signStr).toUpperCase();
		xml = xml.replace("$sign", sign);

		String result = weiXinUtils.postNow(xml, "https://api.mch.weixin.qq.com/pay/unifiedorder");

		// 封装jsapi
		JSAPI api = new JSAPI();
		String appId = WeiXinConf.WECCAPPID;
		String signType = "MD5";
		String timeStamp = System.currentTimeMillis() / 1000 + "";
		Document doc = DocumentHelper.parseText(result);
		Element root = doc.getRootElement();
		String prepayId = root.element("prepay_id").getText();

		String signstr1 = "appId=" + appId + "&nonceStr=" + noncestr + "&package=prepay_id=" + prepayId + "&signType=MD5&timeStamp=" + timeStamp + "&key=" + WeiXinConf.WECC_SHOP_SECRET;
		logger.info("jsapi sign = " + signstr1);
		api.setAppId(appId);
		api.setNonceStr(noncestr);
		api.setPackage1("prepay_id=" + prepayId);
		api.setSignType(signType);
		api.setTimeStamp(timeStamp);
		api.setPaySign(DigestUtils.md5Hex(signstr1).toUpperCase());
		api.setOutTradeNo(outTradeNo);
		logger.info(api.getPaySign() + " --- " + WeiXinUtils.getMD5Code(signstr1).toUpperCase());

		return new GeneralResult<JSAPI>().setValue(api);
	}

	/**
	 * 支付成功后通知接口
	 * 
	 * @throws IOException
	 */
	@RequestMapping(value = "/exchange/pay/notify")
	public void payNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {

		String callback = StreamUtils.copyToString(request.getInputStream(), Charset.forName("utf8"));
		logger.info("支付成功回调 callback xml = " + callback);

		// 校验签名
		Document doc = DocumentHelper.parseText(callback);
		Element root = doc.getRootElement();
		String appid = root.element("appid").getText();
		String attach = root.element("attach").getText();
		String bank_type = root.element("bank_type").getText();
		String cash_fee = root.element("cash_fee").getText();
		String fee_type = root.element("fee_type").getText();
		String is_subscribe = root.element("is_subscribe").getText();
		String mch_id = root.element("mch_id").getText();
		String nonce_str = root.element("nonce_str").getText();
		String openid = root.element("openid").getText();
		String out_trade_no = root.element("out_trade_no").getText();
		String result_code = root.element("result_code").getText();
		String return_code = root.element("return_code").getText();
		String time_end = root.element("time_end").getText();
		String total_fee = root.element("total_fee").getText();
		String trade_type = root.element("trade_type").getText();
		String transaction_id = root.element("transaction_id").getText();
		String sign = root.element("sign").getText();
		String coupon_count = root.elementText("coupon_count");
		String coupon_fee = root.elementText("coupon_fee");
		String coupon_fee_0 = root.elementText("coupon_fee_0");
		String coupon_id_0 = root.elementText("coupon_id_0");

		// 支付失败
		if (!"success".equalsIgnoreCase(result_code)) {
			StreamUtils.copy("<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>", Charset.forName("utf8"), response.getOutputStream());
			return;
		}
		String str = "";

		if (StringUtils.isEmpty(coupon_count))
			str = "appid=" + appid + "&attach=" + attach + "&bank_type=" + bank_type + "&cash_fee=" + cash_fee + "&fee_type=" + fee_type + "&is_subscribe=" + is_subscribe + "&mch_id=" + mch_id + "&nonce_str="
					+ nonce_str + "&openid=" + openid + "&out_trade_no=" + out_trade_no + "&result_code=" + result_code + "&return_code=" + return_code + "&time_end=" + time_end + "&total_fee=" + total_fee
					+ "&trade_type=" + trade_type + "&transaction_id=" + transaction_id + "&key=" + WeiXinConf.WECC_SHOP_SECRET;
		else {
			str = "appid=" + appid + "&attach=" + attach + "&bank_type=" + bank_type + "&cash_fee=" + cash_fee + "&coupon_count=" + coupon_count + "&coupon_fee=" + coupon_fee + "&coupon_fee_0=" + coupon_fee_0
					+ "&coupon_id_0=" + coupon_id_0 + "&fee_type=" + fee_type + "&is_subscribe=" + is_subscribe + "&mch_id=" + mch_id + "&nonce_str=" + nonce_str + "&openid=" + openid + "&out_trade_no="
					+ out_trade_no + "&result_code=" + result_code + "&return_code=" + return_code + "&time_end=" + time_end + "&total_fee=" + total_fee + "&trade_type=" + trade_type + "&transaction_id="
					+ transaction_id + "&key=" + WeiXinConf.WECC_SHOP_SECRET;
		}

		if (!sign.equals(WeiXinUtils.getMD5Code(str).toUpperCase()))
			throw new NoteException("签名校验失败");

		// 处理支付成功后事件
		String userIdStr = attach.split("-")[0];
		String outTradeNo = attach.split("-")[1];
		String fee = attach.split("-")[2];

		OutTradeNoLog log = beanDao.quickQueryOne(OutTradeNoLog.class, "outTradeNo", outTradeNo);




		if (log != null && log.getState() == 0) {
			Long userId = Long.parseLong(userIdStr);

			log.setOutTradeNo(outTradeNo);
			log.setState(1);
			beanDao.save(log);

			// 充值余额,下单购买
			// 调用接口下单
//			String result = WeiXinUtils.get("http://47.97.169.104:20012/buy?price=" + log.getFee());
			String result = WeiXinUtils.get("http://118.31.54.60:20012/buy?price=" + log.getFee());
			JSONObject obj = JSONObject.parseObject(result);
			if (obj.getBooleanValue("success")) {
				// 购买成功
				log.setAmount(obj.getInteger("value"));
				tickerService.addTicker(userId, "wecc", log.getAmount().doubleValue(), "交易所购买");
				logger.error(String.format("交易所购买了%s个‘",log.getAmount().doubleValue()));
				//返佣
				//rw:邀请我的人的钱包
				ReferenceWallet rw = inviteRebateDao.selectRefUserId(userId);
				logger.info(String.format("ReferenceWallet:%s--%s--", rw.getUserId(),rw.getWallet()));
				if(rw != null){
					double rate = Double.parseDouble(beanDao.quickQueryOne(SystemPara.class, "name", "inviteRebatePercentage").getValue());
					inviteRebateDao.updateByVersion(rw.getWallet() + log.getAmount().doubleValue()*rate, rw.getUserId(), rw.getVersion());
					ReferenceDetail rd = new ReferenceDetail();
					rd.setUserId(rw.getUserId());
					rd.setRefUserId(userId);
					rd.setCreateDate(System.currentTimeMillis());
					rd.setChange(rw.getWallet() + log.getAmount().doubleValue()*rate);
					rd.setVersion(rw.getVersion());
					rd.setInvestment(log.getAmount().doubleValue());
					rd.setRebate(log.getAmount().doubleValue()*rate);
					rd.setVersion(rw.getVersion() + 1);
					beanDao.save(rd);
					logger.info(String.format("ReferenceDetail：{%s}--{%s}--{%s}",rd.getId(),rd.getUserId(),rd.getInvestment()));
				}else{
					logger.debug("----------------------------------------------------------------------------------------------");
				}
			}
			log.setBuyMsg(obj.getString("message"));
			beanDao.save(log);

		} else {
			logger.info("outTradeNo 已经存在 : " + outTradeNo);
		}
		StreamUtils.copy("<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>", Charset.forName("utf8"), response.getOutputStream());
	}

	/**
	 * 根据订单查询交易记录,用于查询购买了多少币
	 * 
	 * @param outTradeNo
	 * @return
	 */
	@RequestMapping(value = "/exchange/pay/query")
	public GeneralResult<OutTradeNoLog> queryOutTradeNoLog(Long outTradeNo) {

		return new GeneralResult<OutTradeNoLog>().setValue(beanDao.quickQueryOneById(OutTradeNoLog.class, outTradeNo));
	}

}
